﻿using System;
using System.Collections.Generic;

namespace Conv
{
    public class ConvolutionalFeatureMap:Layer
    {
        public ConvolutionalFeatureMap(List<Layer> fmList, int maskWidth, int maskHeight, Func<double, double> activationFunc, Func<double, double> activationFuncDerivative)
        {
            //setting FM W and H from previous
            Width = fmList[0].Width - (maskWidth - 1);
            Height = fmList[0].Height - (maskHeight - 1);
            Neurons = new Neuron[Width,Height];
            Msk = new Mask(maskWidth, maskHeight);
            for (int i = 0; i < Width; i++)
            {
                for (int j = 0; j < Height; j++)
                {
                    Neurons[i, j] = new Neuron()
                                        {ActivationFunc = activationFunc, ActivationFuncDerivative = activationFuncDerivative};

                }
            }
            foreach (var featureMap in fmList)
            {
                for (int i = 0; i < Width; i++)
                    for (int j = 0; j < Height; j++)
                        ConnectNeuronToFMap(featureMap, Neurons[i, j], Msk, i, j);
            }
        }

        //this constructor connect only to one FM
        public ConvolutionalFeatureMap(Layer fm, int maskWidth, int maskHeight, Func<double, double> activationFunc, Func<double, double> activationFuncDerivative)
        {
            //setting FM W and H from previous
            Width = fm.Width - (maskWidth - 1);
            Height = fm.Height - (maskHeight - 1);
            Neurons = new Neuron[Width, Height];
            Msk = new Mask(maskWidth, maskHeight);
            for (int i = 0; i < Width; i++)
            {
                for (int j = 0; j < Height; j++)
                {
                    Neurons[i, j] = new Neuron() { ActivationFunc = activationFunc, ActivationFuncDerivative = activationFuncDerivative };
                    ConnectNeuronToFMap(fm, Neurons[i, j], Msk, i, j);

                }
            }
        }


        private void ConnectNeuronToFMap(Layer fm, Neuron neuron, Mask weights, int left, int up)
        {
            for (int i = 0; i < weights.Width; i++)
            {
                for (int j = 0; j < weights.Height; j++)
                {
                    neuron.Inputs.Add(new Connection() { From = fm.Neurons[left + i, up + j], To = neuron, Weight = weights.Weights[i, j] });
                }
            }

            //add biass
            neuron.Inputs.Add(new Connection(){From = BiasNeuron,To = neuron, Weight = weights.Biass});

        } 
    }
}